#region License Revision: 0 Last Revised: 6/18/2008 11:00 AM
/******************************************************************************
Copyright (c) Microsoft Corporation.  All rights reserved.


This file is licensed under the Microsoft Public License (Ms-PL). A copy of the Ms-PL should accompany this file. 
If it does not, you can obtain a copy from: 

http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx
******************************************************************************/
#endregion // License
using System;
using System.Windows.Browser;
using System.Diagnostics;
using ScriptInterop;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;

namespace VIEWS // Virtual Earth Wrapper
{
    #region Delegate Definitions
    /// <summary>
    /// Defines the signature for a method that handles general Virtual Earth (JavaScript) events.
    /// </summary>
    /// <param name="obj">
    /// The Virtual Earth (JavaScript) object that contains the event data.
    /// </param>
    /// <returns>
    /// A <see cref="Boolean"/> value that may be used in the JavaScript code. See the Virtaul 
    /// Earth SDK documentation for more information.
    /// </returns>
    public delegate bool VEEventHandler(object obj);

    /// <summary>
    /// Defines the signature for a method that handles Virtual Earth (JavaScript) Load events.
    /// </summary>
    public delegate void VELoadHandler();
    #endregion // Delegate Definitions

    /// <summary>
    /// A managed wrapper for the Virtual Earth JavaScript Map class.
    /// </summary>
    public class VEMap : JSObject
    {
        #region Constants
        /// <summary>String holding JavaScript class name</summary>
        private static string thisClass = "VEMap";
        #endregion // Constants

        #region Constructors
        /// <summary>Construct wrapper from a ScriptObject</summary>
        /// <param name="so">A ScriptObjet from JavaScript.</param>
        public VEMap(ScriptObject so) : base(so) { }

        /// <summary>Initializes a new instance of the VEMap class.</summary>
        /// <param name="containerId" type="String">The ID of the HTML control that will contain the map.</param>
        public VEMap(string containerId)
        {
            ScriptObject = CreateClass(containerId);
        }
        #endregion // Constructors

        #region Callbacks
        /// <summary>A managed callback function that will do the ScriptObject conversion and fire the BirdseyeCompleteEvent on this class</summary>
        [ScriptableMember]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void BirdseyeCompleteManagedCallback(object soBirdseyeScene)
        {
            VEBirdseyeScene scene = null;

            // convert the scene if we have it
            if (soBirdseyeScene != null)
            {
                scene = new VEBirdseyeScene((ScriptObject)soBirdseyeScene);
            }

            // call the event handler
            OnBirdseyeCompleted(new BirdseyeCompletedEventArgs(scene));
        }

        /// <summary>A managed callback function that will do the ScriptObject conversion and fire the FindResultsEvent on this class</summary
        // Parameters should end up like (VEShapeLayer layer, VEFindResult[] arrFindResult, VEPlace[] arrPlace, bool moreItems, string error)
        [ScriptableMember]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void FindManagedCallback(ScriptObject soLayer, ScriptObject soResults, ScriptObject soPlaces, bool moreItems, string error)
        {
            VEShapeLayer layer = null;
            VEFindResult[] arrFindResult = null;
            VEPlace[] arrPlace = null;

            // convert the layer if we have it
            if (soLayer != null)
            {
                layer = new VEShapeLayer(soLayer);
            }

            // convert over the FindResults if we have them
            if (soResults != null)
            {
                arrFindResult = ConvertToArray<VEFindResult>(soResults);
            }

            // convert over the Places if we have them
            if (soPlaces != null)
            {
                arrPlace = ConvertToArray<VEPlace>(soPlaces);
            }

            // Notify
            OnFindCompleted(new FindCompletedEventArgs(layer, arrFindResult, arrPlace, moreItems, error));
        }

        /// <summary>A managed callback function that will do the ScriptObject conversion and fire the Import3DResultsEvent on this class</summary
        [ScriptableMember]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void Import3DModelManagedCallback(object opin, object ostatusCode)
        {
            VEPushpin pin = ScriptObjectUtility.ConvertValue<VEPushpin>(opin);
            VEModelStatusCode status = ScriptEnumConverter.ToModelStatusCode(ScriptObjectUtility.ConvertValue<string>(ostatusCode));

            // call the event handler
            OnImport3DModelCompleted(new Import3DModelCompletedEventArgs(pin, status));
        }

        /// <summary>A managed callback function that will do the ScriptObject conversion and fire the ImportResultsEvent on this class</summary
        [ScriptableMember]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void ImportShapeLayerDataManagedCallback(object obj)
        {
            ScriptObject soShapeLayer = (ScriptObject)obj;
            VEShapeLayer layer = null;

            // convert the layer if we have it
            if (soShapeLayer != null)
            {
                layer = new VEShapeLayer(soShapeLayer);
            }

            // call the event handler
            OnImportShapeLayerDataCompleted(new ImportShapeLayerDataCompletedEventArgs(layer));
        }

        /// <summary>A managed callback function that will do the ScriptObject conversion and fire the RouteResultsEvent on this class</summary
        [ScriptableMember]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void RouteManagedCallback(object obj)
        {
            ScriptObject soRoute = (ScriptObject)obj;
            VERoute route = null;

            // convert the layer if we have it
            if (soRoute != null)
            {
                route = new VERoute(soRoute);
            }

            // call the event handler
            OnRouteCompleted(new RouteCompletedEventArgs(route));
        }
        #endregion // Callbacks

        #region Internal Overrides / Event Handlers
        #region Mouse Events
        [ScriptableMember]
        private bool InnerClick(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnClick(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerDoubleClick(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnDoubleClick(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerMouseDown(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnMouseDown(e);
            return e.Handled;
        }

        // Note   This is not supported in 3D mode.
        [ScriptableMember]
        private bool InnerMouseMove(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnMouseMove(e);
            return e.Handled;
        }

        // Occurs when the mouse cursor moves over a VEShape Class object.
        [ScriptableMember]
        private bool InnerMouseOver(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnMouseOver(e);
            return e.Handled;
        }

        // Occurs when the mouse cursor moves away from a VEShape object.
        [ScriptableMember]
        private bool InnerMouseOut(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnMouseOut(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerMouseUp(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnMouseUp(e);
            return e.Handled;
        }

        // Note   This method is not supported in 3D mode, and the coordinate values returned in Firefox 1.5 and 2.0 are not correct.
        [ScriptableMember]
        private bool InnerMouseWheel(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnMouseWheel(e);
            return e.Handled;
        }
        #endregion // Mouse Events

        #region Keyboard Events
        [ScriptableMember]
        private bool InnerKeyDown(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnKeyDown(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerKeyPress(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnKeyPress(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerKeyUp(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnKeyUp(e);
            return e.Handled;
        }
        #endregion // Keyboard Events

        #region General Events
        [ScriptableMember]
        private bool InnerBirdseyeChanged(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnBirdseyeChanged(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerBirdseyeEntered(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnBirdseyeEntered(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerBirdseyeLeft(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnBirdseyeLeft(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerError(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnError(e);
            return e.Handled;
        }

        [ScriptableMember]
        private void InnerMapLoaded()
        {
            OnMapLoaded(EventArgs.Empty);
        }

        [ScriptableMember]
        private bool InnerMapStyleChanged(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnMapStyleChanged(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerModeInitialized(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnModeInitialized(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerModeNotAvailable(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnModeNotAvailable(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerPanEnded(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnPanEnded(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerPanStarted(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnPanStarted(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerResized(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnResized(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerViewChanged(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnViewChanged(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerZoomEnded(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnZoomEnded(e);
            return e.Handled;
        }

        [ScriptableMember]
        private bool InnerZoomStarted(object data)
        {
            VEMapEventArgs e = new VEMapEventArgs((ScriptObject)data);
            OnZoomStarted(e);
            return e.Handled;
        }
        #endregion // General Events
        #endregion // Internal Overrides / Event Handlers

        #region Overrides / Event Handlers
        /// <summary>
        /// Called when the underlying ScriptObject has been assigned.
        /// </summary>
        /// <remarks>
        /// This override only happens once during the lifetime of the script object.
        /// </remarks>
        protected override void OnScriptObjectAssigned()
        {
            // Pass to base first
            base.OnScriptObjectAssigned();

            /* Map Load Handler */
            SetProperty("onLoadMap", (VELoadHandler)InnerMapLoaded);

            /* Mouse Events */
            AttachEvent("onclick", InnerClick);
            AttachEvent("ondoubleclick", InnerDoubleClick);
            AttachEvent("onmousedown", InnerMouseDown);
            AttachEvent("onmousemove Event ", InnerMouseMove);
            AttachEvent("onmouseout", InnerMouseOut);
            AttachEvent("onmouseover", InnerMouseOver);
            AttachEvent("onmouseup", InnerMouseUp);
            AttachEvent("onmousewheel", InnerMouseWheel);

            /* Key Events */
            AttachEvent("onkeydown", InnerKeyDown);
            AttachEvent("onkeypress", InnerKeyPress);
            AttachEvent("onkeyup", InnerKeyUp);

            /* General Events */
            AttachEvent("onchangemapstyle", InnerMapStyleChanged);
            AttachEvent("onchangeview", InnerViewChanged);
            AttachEvent("onendpan", InnerPanEnded);
            AttachEvent("onendzoom", InnerZoomEnded);
            AttachEvent("onerror", InnerError);
            AttachEvent("oninitmode", InnerModeInitialized);
            AttachEvent("onmodenotavailable", InnerModeNotAvailable);
            AttachEvent("onobliquechange", InnerBirdseyeChanged);
            AttachEvent("onobliqueenter", InnerBirdseyeEntered);
            AttachEvent("onobliqueleave", InnerBirdseyeLeft);
            AttachEvent("onresize", InnerResized);
            AttachEvent("onstartpan", InnerPanStarted);
            AttachEvent("onstartzoom", InnerZoomStarted);
        }
        #endregion // Overrides / Event Handlers

        #region Overridables / Event Triggers
        #region Mouse Overrides
        /// <summary>
        /// Raises the <see cref="Click"/> event.
        /// </summary>
        protected virtual void OnClick(VEMapEventArgs e)
        {
            if (Click != null)
            {
                Click(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="DoubleClick"/> event.
        /// </summary>
        protected virtual void OnDoubleClick(VEMapEventArgs e)
        {
            if (DoubleClick != null)
            {
                DoubleClick(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="MouseDown"/> event.
        /// </summary>
        protected virtual void OnMouseDown(VEMapEventArgs e)
        {
            if (MouseDown != null)
            {
                MouseDown(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="MouseMove"/> event.
        /// </summary>
        protected virtual void OnMouseMove(VEMapEventArgs e)
        {
            if (MouseMove != null)
            {
                MouseMove(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="MouseOut"/> event.
        /// </summary>
        protected virtual void OnMouseOut(VEMapEventArgs e)
        {
            if (MouseOut != null)
            {
                MouseOut(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="MouseOver"/> event.
        /// </summary>
        protected virtual void OnMouseOver(VEMapEventArgs e)
        {
            if (MouseOver != null)
            {
                MouseOver(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="MouseUp"/> event.
        /// </summary>
        protected virtual void OnMouseUp(VEMapEventArgs e)
        {
            if (MouseUp != null)
            {
                MouseUp(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="MouseWheel"/> event.
        /// </summary>
        protected virtual void OnMouseWheel(VEMapEventArgs e)
        {
            if (MouseWheel != null)
            {
                MouseWheel(this, e);
            }
        }
        #endregion // Mouse Overrides

        #region Keyboard Overrides
        /// <summary>
        /// Raises the <see cref="KeyDown"/> event.
        /// </summary>
        protected virtual void OnKeyDown(VEMapEventArgs e)
        {
            if (KeyDown != null)
            {
                KeyDown(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="KeyPress"/> event.
        /// </summary>
        protected virtual void OnKeyPress(VEMapEventArgs e)
        {
            if (KeyPress != null)
            {
                KeyPress(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="KeyUp"/> event.
        /// </summary>
        protected virtual void OnKeyUp(VEMapEventArgs e)
        {
            if (KeyUp != null)
            {
                KeyUp(this, e);
            }
        }
        #endregion // Keyboard Overrides

        #region General Overrides
        /// <summary>
        /// Raises the <see cref="BirdseyeChanged"/> event.
        /// </summary>
        protected virtual void OnBirdseyeChanged(VEMapEventArgs e)
        {
            if (BirdseyeChanged != null)
            {
                BirdseyeChanged(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="BirdseyeCompleted"/> event.
        /// </summary>
        protected virtual void OnBirdseyeCompleted(BirdseyeCompletedEventArgs e)
        {
            if (BirdseyeCompleted != null)
            {
                BirdseyeCompleted(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="BirdseyeEntered"/> event.
        /// </summary>
        protected virtual void OnBirdseyeEntered(VEMapEventArgs e)
        {
            if (BirdseyeEntered != null)
            {
                BirdseyeEntered(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="BirdseyeLeft"/> event.
        /// </summary>
        protected virtual void OnBirdseyeLeft(VEMapEventArgs e)
        {
            if (BirdseyeLeft != null)
            {
                BirdseyeLeft(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="Error"/> event.
        /// </summary>
        protected virtual void OnError(VEMapEventArgs e)
        {
            if (Error != null)
            {
                Error(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="FindCompleted"/> event.
        /// </summary>
        protected virtual void OnFindCompleted(FindCompletedEventArgs e)
        {
            if (FindCompleted != null)
            {
                FindCompleted(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="Import3DModelCompleted"/> event.
        /// </summary>
        protected virtual void OnImport3DModelCompleted(Import3DModelCompletedEventArgs e)
        {
            if (Import3DModelCompleted != null)
            {
                Import3DModelCompleted(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="ImportCompleted"/> event.
        /// </summary>
        protected virtual void OnImportShapeLayerDataCompleted(ImportShapeLayerDataCompletedEventArgs e)
        {
            if (ImportShapeLayerDataCompleted != null)
            {
                ImportShapeLayerDataCompleted(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="MapLoaded"/> event.
        /// </summary>
        protected virtual void OnMapLoaded(EventArgs e)
        {
            if (MapLoaded != null)
            {
                MapLoaded(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="MapStyleChanged"/> event.
        /// </summary>
        protected virtual void OnMapStyleChanged(VEMapEventArgs e)
        {
            if (MapStyleChanged != null)
            {
                MapStyleChanged(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="ModeInitialized"/> event.
        /// </summary>
        protected virtual void OnModeInitialized(VEMapEventArgs e)
        {
            if (ModeInitialized != null)
            {
                ModeInitialized(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="ModeNotAvailable"/> event.
        /// </summary>
        protected virtual void OnModeNotAvailable(VEMapEventArgs e)
        {
            if (ModeNotAvailable != null)
            {
                ModeNotAvailable(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="PanEnded"/> event.
        /// </summary>
        protected virtual void OnPanEnded(VEMapEventArgs e)
        {
            if (PanStarted != null)
            {
                PanStarted(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="PanStarted"/> event.
        /// </summary>
        protected virtual void OnPanStarted(VEMapEventArgs e)
        {
            if (PanEnded != null)
            {
                PanEnded(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="Resized"/> event.
        /// </summary>
        protected virtual void OnResized(VEMapEventArgs e)
        {
            if (Resized != null)
            {
                Resized(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="RouteCompleted"/> event.
        /// </summary>
        protected virtual void OnRouteCompleted(RouteCompletedEventArgs e)
        {
            if (RouteCompleted != null)
            {
                RouteCompleted(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="ViewChanged"/> event.
        /// </summary>
        protected virtual void OnViewChanged(VEMapEventArgs e)
        {
            if (ViewChanged != null)
            {
                ViewChanged(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="ZoomEnded"/> event.
        /// </summary>
        protected virtual void OnZoomEnded(VEMapEventArgs e)
        {
            if (ZoomEnded != null)
            {
                ZoomEnded(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="ZoomStarted"/> event.
        /// </summary>
        protected virtual void OnZoomStarted(VEMapEventArgs e)
        {
            if (ZoomStarted != null)
            {
                ZoomStarted(this, e);
            }
        }
        #endregion // General Overrides
        #endregion // Overridables / Event Triggers

        #region Public Methods
        /// <summary>Adds a custom control to the map.</summary>
        /// <param name="element">An HTML element that contains the control to be added.</param>
        public void AddControl(HtmlElement element)
        {
            Invoke("AddControl", element);
        }

        /// <summary>Adds a custom control to the map.</summary>
        /// <param name="element">An HTML element that contains the control to be added.</param>
        /// <param name="zIndex" type="Number">The z-order for the control. Optional.</param>
        public void AddControl(HtmlElement element, int zIndex)
        {
            Invoke("AddControl", element, zIndex);
        }

        /// <summary>Adds a VEShape Class object or array of VEShape pushpin objects to the base layer.</summary>
        /// <param name="shape" type="VEShape">The VEShape object to be added. Required.</param>
        public void AddShape(VEShape shape)
        {
            Invoke("AddShape", (ScriptObject)shape);
        }

        /// <summary>Adds a VEShape Class object or array of VEShape pushpin objects to the base layer.</summary>
        /// <param name="shape" type="VEShape">An array of VEShape pushpin objects to be added. Required.</param>
        public void AddShape(VEShape[] shapes)
        {
            JSArray<ScriptObject> arrSO = ConvertToScriptObjectJSArray(shapes);
            Invoke("AddShape", (ScriptObject)arrSO);
        }

        /// <summary>Adds the specified shape layer to the map.  If this layer reference already exists on the map, an exception is thrown, and no new layer is created.</summary>
        /// <param name="layer" type="VEShapeLayer">A reference to the layer to add.</param>
        public void AddShapeLayer(VEShapeLayer layer)
        {
            Invoke("AddShapeLayer", (ScriptObject)layer);
        }

        /// <summary>Adds a tile layer to the map, and if the visibleOnLoad parameter is true, it also shows it on the map.</summary>
        /// <param name="layerSource" type="VETileSourceSpecification">The VETileSourceSpecification Class object representing the source of the tile layer. Required.</param>
        /// <param name="visibleOnLoad" type="Boolean">The VETileSourceSpecification Class object representing the source of the tile layer. Required.</param>
        public void AddTileLayer(VETileSourceSpecification layerSource, bool visibleOnLoad)
        {
            Invoke("AddTileLayer", (ScriptObject)layerSource, visibleOnLoad);
        }

        /// <summary>Attaches a Map Control event to a specified function.</summary>
        /// <param name="event" type="String">The name of the Map Control event that generates the call.</param>
        /// <param name="handler">The function to run when the event fires. Pass a standard EventHandler delegate</param>
        public void AttachEvent(string eventName, VEEventHandler handler)
        {
            Invoke("AttachEvent", eventName, handler);
        }

        /// <summary>Removes all shapes, shape layers, and search results on the map. Also removes the route from the map, if one is displayed.  The Clear method does not remove custom tile layers from the map.</summary>
        public void Clear()
        {
            Invoke("Clear");
        }

        /// <summary>Clears out all of the default Virtual Earth info box CSS styles.</summary>
        public void ClearInfoBoxStyles()
        {
            Invoke("ClearInfoBoxStyles");
        }

        /// <summary>Deletes all shape layers, along with any shapes within the layers.</summary>
        public void DeleteAllShapeLayers()
        {
            Invoke("DeleteAllShapeLayers");
        }

        /// <summary>Deletes all shapes in all layers, leaving empty layers behind.</summary>
        public void DeleteAllShapes()
        {
            Invoke("DeleteAllShapes");
        }

        /// <summary>Removes the specified control from the map.</summary>
        /// <param name="element">An HTML element that contains the control to be deleted</param>
        public void DeleteControl(HtmlElement element)
        {
            Invoke("DeleteControl", element);
        }

        /// <summary>Clears the current route (VERoute Class object) from the map.</summary>
        public void DeleteRoute()
        {
            Invoke("DeleteRoute");
        }

        /// <summary>Deletes a VEShape Class object from any layer, including the base map layer.</summary>
        /// <param name="shape" type="VEShape">The reference to the VEShape object to be deleted. Required.</param>
        public void DeleteShape(VEShape shape)
        {
            Invoke("DeleteShape", (ScriptObject)shape);
        }

        /// <summary>Deletes the specified shape layer from the map.</summary>
        /// <param name="layer" type="VEShapeLayer">A reference to the layer to delete. Required.</param>
        public void DeleteShapeLayer(VEShapeLayer layer)
        {
            Invoke("DeleteShapeLayer", (ScriptObject)layer);
        }

        /// <summary>Completely removes a tile layer from the map.</summary>
        /// <param name="layerId" type="String">The ID of the layer to be deleted.</param>
        public void DeleteTileLayer(string layerId)
        {
            Invoke("DeleteTileLayer", layerId);
        }

        /// <summary>Detaches the specified map control event so that it no longer calls the specified function.</summary>
        /// <param name="event" type="String">The name of the map control event that generates the call.</param>
        /// <param name="func">The function that was specified to run when the event fired. Delegates of standard EventHandler pattern are supported</param>
        public void DetachEvent(string eventName, VEEventHandler func)
        {
            Invoke("DetachEvent", eventName, func);
        }

        /// <summary>Deletes the VEMap object and releases any associated resources.</summary>
        public void Dispose()
        {
            // since we are wrapping this, calling Dispose from a CLR standpoint might have different semantics. However, we will assume that calling dispose multiple times is fine.
            Invoke("Dispose");
        }

        /// <summary>Stops the continuous map panning initiated by a call to the StartContinuousPan Method.</summary>
        public void EndContinuousPan()
        {
            Invoke("EndContinuousPan");
        }

        /// <summary>Performs a what (business) search and/or a where (location) search. At least one of these two parameters is required.</summary>
        /// <param name="what" type="String">The business name, category, or other item searched for. This parameter must be supplied for a pushpin to be included in the results.</param>
        /// <param name="where" type="String">The address or place name of the area searched for. </param>
        public void Find(string what, string where)
        {
            Invoke("Find", what, where);
        }

        /// <summary>Performs a what (business) search and/or a where (location) search. At least one of these two parameters is required.</summary>
        /// <param name="what" type="String">The business name, category, or other item searched for. This parameter must be supplied for a pushpin to be included in the results.</param>
        /// <param name="where" type="String">The address or place name of the area searched for. </param>
        /// <param name="findOptions" type="FindOptions">A reference to a structure with other find options</param>
        public void Find(string what, string where, FindOptions findOptions)
        {
            if (findOptions.Callback)
                HtmlPage.Window.Invoke("FindJS", (ScriptObject)this, what, where, ScriptEnumConverter.ToString(VEFindType.Businesses), (ScriptObject)findOptions.ShapeLayer, findOptions.StartIndex, findOptions.NumberOfResults, findOptions.ShowResults, findOptions.CreateResults, findOptions.UseDefaultDisambiguation, findOptions.SetBestMapView);
            else
                Invoke("Find", what, where, ScriptEnumConverter.ToString(VEFindType.Businesses), (ScriptObject)findOptions.ShapeLayer, findOptions.StartIndex, findOptions.NumberOfResults, findOptions.ShowResults, findOptions.CreateResults, findOptions.UseDefaultDisambiguation, findOptions.SetBestMapView, null);
        }

        /// <summary>Performs a what (business) search and/or a where (location) search. At least one of these two parameters is required.</summary>
        /// <param name="what" type="String">The business name, category, or other item searched for. This parameter must be supplied for a pushpin to be included in the results.</param>
        /// <param name="where" type="VEPlace">The place searched for</param>
        /// <param name="findOptions" type="FindOptions">A reference to a structure with other find options</param>
        public void Find(string what, VEPlace where, FindOptions findOptions)
        {
            if (findOptions.Callback)
                HtmlPage.Window.Invoke("FindJS", (ScriptObject)this, what, (ScriptObject)where, ScriptEnumConverter.ToString(VEFindType.Businesses), (ScriptObject)findOptions.ShapeLayer, findOptions.StartIndex, findOptions.NumberOfResults, findOptions.ShowResults, findOptions.CreateResults, findOptions.UseDefaultDisambiguation, findOptions.SetBestMapView);
            else
                Invoke("Find", what, (ScriptObject)where, ScriptEnumConverter.ToString(VEFindType.Businesses), (ScriptObject)findOptions.ShapeLayer, findOptions.StartIndex, findOptions.NumberOfResults, findOptions.ShowResults, findOptions.CreateResults, findOptions.UseDefaultDisambiguation, findOptions.SetBestMapView, null);
        }

        ///// <summary>Performs a what (business) search and/or a where (location) search. At least one of these two parameters is required.</summary>
        ///// <param name="what" type="String">The business name, category, or other item searched for. This parameter must be supplied for a pushpin to be included in the results.</param>
        ///// <param name="where" type="String">The address or place name of the area searched for. </param>
        ///// <param name="shapeLayer" type="VEShapeLayer">A reference to the VEShapeLayer Class object that contain the pins that result from this search if it is a "what" component. Optional. If the shape layer is not specified, the pins are added to the base map layer. If the reference is not a valid VEShapeLayer reference, an exception is thrown.</param>
        ///// <param name="startIndex" type="Number">The beginning index of the results returned. Optional. Default is 0.</param>
        ///// <param name="numberOfResults" type="Number">The number of results to be returned, starting at startIndex. The default is 10, the minimum is 1, and the maximum is 20.</param>
        ///// <param name="showResults" type="Boolean">A Boolean object that determines whether the resulting pushpins are visible. Optional. Default is true.</param>		
        ///// <param name="createResults" type="Boolean">A Boolean true or false that determines whether pushpins are created when the what parameter is supplied. Optional. If set to the default true, pushpins are created. If set to false: The array of VEFindResult Class objects is still present in the callback, but no pushpin layer is created; The VEShapeLayer reference field within the callback is null; Each VEFindResult object's corresponding Shape property is null.</param>		
        ///// <param name="useDefaultDisambiguation" type="Boolean">A Boolean true or false that determines whether the default disambiguation box appears when multiple location matches are possible. Optional. Default is true. If set to true, the default disambiguation box appears. If set to false the default disambiguation box is not displayed.</param>		
        ///// <param name="setBestMapView" type="Boolean">A Boolean true or false that determines whether the map view is moved to the first location match. If set to true, the map view is moved to the first location match. Default is true.</param>		
        ///// <param name="callback">Fire the  FindResultsEvent with the find results. If useDefaultDisambiguation is set to true, this event will not be fired until the user has made a disambiguation choice. Optional. </param>
        //private void Find(string what, string where, VEShapeLayer shapeLayer, int startIndex, int numberOfResults, bool showResults, bool createResults, bool useDefaultDisambiguation, bool setBestMapView, bool callback)
        //{
        //    // call a proxy function in Javascript because our callbacks won't pass the (typeof = "function") test used to validate parameters
        //    if (callback)
        //        HtmlPage.Window.Invoke("FindJS", (ScriptObject)this, what, where, ScriptEnumConverter.ToString(VEFindType.Businesses), (ScriptObject)shapeLayer, startIndex, numberOfResults, showResults, createResults, useDefaultDisambiguation, setBestMapView);
        //    else
        //        Invoke("Find", what, where, ScriptEnumConverter.ToString(VEFindType.Businesses), (ScriptObject)shapeLayer, startIndex, numberOfResults, showResults, createResults, useDefaultDisambiguation, setBestMapView, null);
        //}

        /// <summary>Draws a multi-point route on the map and sends details about the route to a callback function.</summary>
        /// <param name="locations" type="Array">An array of VELatLong Class objects specifying the points through which the route must pass. </param>
        /// <param name="options" type="VERouteOptions">A VERouteOptions Class object specifying the routing options.</param>	 
        public void GetDirections(VELatLong[] locations, VERouteOptions options)
        {
            JSArray<ScriptObject> arrLoc = ConvertToScriptObjectJSArray(locations);
            Invoke("GetDirections", (ScriptObject)arrLoc, (ScriptObject)options);
        }

        /// <summary>Draws a multi-point route on the map and sends details about the route to a callback function.</summary>
        /// <param name="locations" type="Array">An array of string objects specifying the points through which the route must pass. </param>
        /// <param name="options" type="VERouteOptions">A VERouteOptions Class object specifying the routing options.</param>	 
        public void GetDirections(string[] locations, VERouteOptions options)
        {
            //JSArray<string> arrStr = new JSArray<string>();
            //for (int i = 0; i < locations.Length; i++)
            //{
            //    arrStr[i] = locations[i];
            //}

            Invoke("GetDirections", locations /*(ScriptObject)arrStr*/, (ScriptObject)options);
        }

        /// <summary>Draws a multi-point route on the map and sends details about the route to a callback function.</summary>
        /// <param name="locations" type="Array">An array of objects specifying the points through which the route must pass. The points can be either VELatLong Class objects or String objects.</param>
        /// <param name="options" type="VERouteOptions">A VERouteOptions Class object specifying the routing options.</param>	 
        public void GetDirections(object[] locations, VERouteOptions options)
        {
            int ilim = locations.Length;
            object[] objects = new object[ilim];
            for (int i = 0; i < ilim; ++i)
            {
                if (locations[i] is VELatLong)
                    objects[i] = (ScriptObject)locations[i];
                else if (locations[i] is string)
                    objects[i] = locations[i];
                else
                    Debug.Assert(false, "Invalid type in array");
            }
            if (options.RouteCallback != null)
                HtmlPage.Window.Invoke("GetDirectionsJS", (ScriptObject)this, locations, (ScriptObject)options);
            else
                Invoke("GetDirections", objects, (ScriptObject)options);
        }

        /// <summary>Gets the reference to a VEShape Class object based on its internal identifier.</summary>
        /// <param name="ID" type="String">The identifier of the shape to retrieve. Required.</param>
        /// <returns type="VEShape"></returns>  
        public VEShape GetShapeById(string id)
        {
            ScriptObject so = Invoke<ScriptObject>("GetShapeByID", id);
            if (so == null)
                return null;
            VEShape shape = VEShape.GetShapeObject(so);
            // get the specific type of shape object.
            return shape;
        }

        /// <summary>Gets the reference to a VEShapeLayer Class object based on its index.</summary>
        /// <param name="index" type="Number">The index of the layer that you wish to retrieve. Required.</param>
        /// <returns type="VEShapeLayer"></returns>  
        public VEShapeLayer GetShapeLayerByIndex(int index)
        {
            ScriptObject so = Invoke<ScriptObject>("GetShapeLayerByIndex", index);
            if (so == null)
                return null;
            VEShapeLayer layer = new VEShapeLayer(so);
            return layer;
        }

        /// <summary>Gets a tile layer based upon its identifier.</summary>
        /// <param name="id" type="String">The unique identifier of the tile layer.</param>
        /// <returns type="VETileSourceSpecification"></returns>  
        public VETileSourceSpecification GetTileLayerById(string id)
        {
            ScriptObject so = Invoke<ScriptObject>("GetTileLayerByID", id);
            if (so == null)
                return null;
            VETileSourceSpecification tileSource = new VETileSourceSpecification(so);
            return tileSource;
        }

        /// <summary>Gets a tile layer based upon its identifier.</summary>
        /// <param name="index" type="Number">The index into the list of tile layers. The value ranges from 0 to GetTileLayerCount.</param>
        /// <returns type="VETileSourceSpecification"></returns>  
        public VETileSourceSpecification GetTileLayerByIndex(int index)
        {
            ScriptObject so = Invoke<ScriptObject>("GetTileLayerByIndex", index);
            if (so == null)
                return null;
            VETileSourceSpecification tileSource = new VETileSourceSpecification(so);
            return tileSource;
        }

        /// <summary>In 3D mode, hides the default user interface for controlling the map in 3D mode. By default, this control is shown.</summary>
        public void Hide3DNavigationControl()
        {
            Invoke("Hide3DNavigationControl");
        }

        /// <summary>Hides all of the shape layers on the map.</summary>
        public void HideAllShapeLayers()
        {
            Invoke("HideAllShapeLayers");
        }

        /// <summary>Hides the specified control from view.</summary>
        /// <param name="element" type="String">An HTML element that contains the control to be hidden.</param>
        public void HideControl(HtmlElement element)
        {
            Invoke("HideControl", element);
        }

        /// <summary>Hides the default user interface for controlling the map (the compass and the zoom control).</summary>
        public void HideDashboard()
        {
            Invoke("HideDashboard");
        }

        /// <summary>Removes the Find control from the map.</summary>
        public void HideFindControl()
        {
            Invoke("HideFindControl");
        }

        /// <summary>Hides a shape's custom or default info box.  There can be only one info box on the screen at a given time. The method will hide the currently visible info box.</summary>
        public void HideInfoBox()
        {
            Invoke("HideInfoBox");
        }

        /// <summary>Hides the mini map from view.</summary>
        public void HideMiniMap()
        {
            Invoke("HideMiniMap");
        }

        /// <summary>Hides the scale bar from view.</summary>
        public void HideScalebar()
        {
            Invoke("HideScalebar");
        }

        /// <summary>Hides the specified control from view.</summary>
        /// <param name="layerID" type="String">The ID of the layer to be hidden.</param>
        public void HideTileLayer(string layerId)
        {
            Invoke("HideTileLayer", layerId);
        }

        /// <summary>Hides the traffic legend.</summary>
        public void HideTrafficLegend()
        {
            Invoke("HideTrafficLegend");
        }

        /// <summary>
        /// Imports a model data file and displays a 3D model on the map.
        /// </summary>
        /// <param name="modelShapeSource">
        /// A <see cref="VEModelSourceSpecification"/> Class object specifying the model data to import.
        /// </param>
        /// <param name="callback">
        /// The name of the function that is called after the data has been imported. See below for the arguments received by the callback.
        /// </param>
        /// <param name="latLong">
        /// A <see cref="VELatLong"/> Class object that specifies the point at which to place the origin of the model.
        /// </param>
        /// <param name="orientation">
        /// A <see cref="VEModelOrientation"/> Class object that specifies the orientation of the model on the map.
        /// </param>
        /// <param name="scale">
        /// A <see cref="VEModelScale"/> Class object that specifies the scale of the model.
        /// </param>
        /// <returns>
        /// A <see cref="VEPushpin"/> corresponding to the associated 3D model. This is also returned to the function specified in the callback parameter.
        /// </returns>
        public VEPushpin Import3DModel(VEModelSourceSpecification modelShapeSource, bool callback, VELatLong latLong, VEModelOrientation orientation, VEModelScale scale)
        {
            ScriptObject result = null;

            if (callback)
            {
                result = (ScriptObject)HtmlPage.Window.Invoke("Import3DModelJS", (ScriptObject)this, (ScriptObject)modelShapeSource, (ScriptObject)latLong, (ScriptObject)orientation, (ScriptObject)scale);
            }
            else
            {
                result = (ScriptObject)Invoke("Import3DModel", (ScriptObject)modelShapeSource, callback, (ScriptObject)modelShapeSource, (ScriptObject)latLong, (ScriptObject)orientation, (ScriptObject)scale);
            }

            return new VEPushpin(result);
        }

        /// <summary>Imports data from a GeoRSS feed, Live Search Maps (http://maps.live.com) collection, or KML URL.</summary>
        /// <param name="shapeSource" type="VEShapeSourceSpecification"> VEShapeSourceSpecification Class object specifying the imported shape data.</param>
        /// <param name="callback" type="Boolean">A boolean value that indicates if the ImportResultsEvent should be fired after the data has been imported.</param>
        /// <param name="setBestView" type="Boolean">A Boolean value that specifies whether the map view is changed to the best view for the layer.</param>
        public void ImportShapeLayerData(VEShapeSourceSpecification shapeSource, bool callback, bool setBestView)
        {
            if (callback)
                HtmlPage.Window.Invoke("ImportShapeLayerDataJS", (ScriptObject)this, (ScriptObject)shapeSource, setBestView);
            else
                Invoke("ImportShapeLayerData", (ScriptObject)shapeSource, callback, setBestView);
        }

        /// <summary>Determines whether the bird's eye map style is available in the current map view.</summary>
        /// <returns type="Boolean"></returns>		
        public bool IsBirdseyeAvailable()
        {
            return Invoke<bool>("IsBirdseyeAvailable");
        }

        /// <summary>Converts a VELatLong Class object (latitude/longitude pair) to the corresponding pixel on the map.</summary>
        /// <param name="LatLong" type="VELatLong">A VELatLong Class object that contains the latitude and longitude of a point.</param>
        public VEPixel LatLongToPixel(VELatLong latLong)
        {
            ScriptObject so = Invoke<ScriptObject>("LatLongToPixel", (ScriptObject)latLong);
            var ret = new VEPixel(so);
            return ret;
        }

        /// <summary>Loads the specified map. All parameters are optional.</summary>
        public void LoadMap()
        { Invoke("LoadMap"); }

        /// <summary>Loads the specified map. All parameters are optional.</summary>
        /// <param name="latLong" type="VELatLong">A VELatLong Class object that represents the center of the map. Optional.</param>
        public void LoadMap(VELatLong latLong)
        { Invoke("LoadMap", (ScriptObject)latLong); }

        /// <summary>Loads the specified map. All parameters are optional.</summary>
        /// <param name="latLong" type="VELatLong">A VELatLong Class object that represents the center of the map. Optional.</param>
        /// <param name="zoom" type="Number">The zoom level to display. Valid values range from 1 through 19. Optional. Default is 4.</param>
        public void LoadMap(VELatLong latLong, int zoom)
        { Invoke("LoadMap", (ScriptObject)latLong, zoom); }

        /// <summary>Loads the specified map. All parameters are optional.</summary>
        /// <param name="latLong" type="VELatLong">A VELatLong Class object that represents the center of the map. Optional.</param>
        /// <param name="zoom" type="Number">The zoom level to display. Valid values range from 1 through 19. Optional. Default is 4.</param>
        /// <param name="style" type="VEMapStyle">A VEMapStyle Enumeration value specifying the map style. Optional. Default is VEMapStyle.Road.</param>
        public void LoadMap(VELatLong latLong, int zoom, VEMapStyle style)
        {
            string strStyle = new string((char)style, 1); // convert to string
            Invoke("LoadMap", (ScriptObject)latLong, zoom, strStyle);
        }

        /// <summary>Loads the specified map. All parameters are optional.</summary>
        /// <param name="latLong" type="VELatLong">A VELatLong Class object that represents the center of the map. Optional.</param>
        /// <param name="zoom" type="Number">The zoom level to display. Valid values range from 1 through 19. Optional. Default is 4.</param>
        /// <param name="style" type="VEMapStyle">A VEMapStyle Enumeration value specifying the map style. Optional. Default is VEMapStyle.Road.</param>
        /// <param name="options">
        /// A <see cref="LoadMapOptions"/> that provides additional map loading options.
        /// </param>
        public void LoadMap(VELatLong latLong, int zoom, VEMapStyle style, LoadMapOptions options)
        {
            if (options == null) throw new ArgumentNullException("options");
            string strStyle = new string((char)style, 1); // convert to string
            if (options.MapOptions != null)
            {
                Invoke("LoadMap", (ScriptObject)latLong, zoom, strStyle, options.IsFixed, options.Mode, options.ShowSwitch, options.TileBuffer, options.MapOptions);
            }
            else
            {
                Invoke("LoadMap", (ScriptObject)latLong, zoom, strStyle, options.IsFixed, options.Mode, options.ShowSwitch, options.TileBuffer);
            }
        }

        ///// <summary>Loads the specified map. All parameters are optional.</summary>
        ///// <param name="latLong" type="VELatLong">A VELatLong Class object that represents the center of the map. Optional.</param>
        ///// <param name="zoom" type="Number">The zoom level to display. Valid values range from 1 through 19. Optional. Default is 4.</param>
        ///// <param name="style" type="VEMapStyle">A VEMapStyle Enumeration value specifying the map style. Optional. Default is VEMapStyle.Road.</param>
        ///// <param name="setFixed" type="Boolean">Specifies whether the map view is displayed as a fixed map that the user cannot change. Optional. Default is false.</param>
        //public void LoadMap(VELatLong latLong, int zoom, VEMapStyle style, bool setFixed)
        //{
        //    string strStyle = new string((char)style, 1); // convert to string
        //    Invoke("LoadMap", (ScriptObject)latLong, zoom, strStyle, setFixed);
        //}

        ///// <summary>Loads the specified map. All parameters are optional.</summary>
        ///// <param name="latLong" type="VELatLong">A VELatLong Class object that represents the center of the map. Optional.</param>
        ///// <param name="zoom" type="Number">The zoom level to display. Valid values range from 1 through 19. Optional. Default is 4.</param>
        ///// <param name="style" type="VEMapStyle">A VEMapStyle Enumeration value specifying the map style. Optional. Default is VEMapStyle.Road.</param>
        ///// <param name="setFixed" type="Boolean">Specifies whether the map view is displayed as a fixed map that the user cannot change. Optional. Default is false.</param>
        ///// <param name="mode" type="VEMapMode">Specifies whether to load the map in 2D or 3D mode. Optional. Default is VEMapMode.Mode2D.</param>
        //public void LoadMap(VELatLong latLong, int zoom, VEMapStyle style, bool setFixed, VEMapMode mode)
        //{
        //    string strStyle = new string((char)style, 1); // convert to string
        //    Invoke("LoadMap", (ScriptObject)latLong, zoom, strStyle, setFixed, mode);
        //}

        ///// <summary>Loads the specified map. All parameters are optional.</summary>
        ///// <param name="latLong" type="VELatLong">A VELatLong Class object that represents the center of the map. Optional.</param>
        ///// <param name="zoom" type="Number">The zoom level to display. Valid values range from 1 through 19. Optional. Default is 4.</param>
        ///// <param name="style" type="VEMapStyle">A VEMapStyle Enumeration value specifying the map style. Optional. Default is VEMapStyle.Road.</param>
        ///// <param name="setFixed" type="Boolean">Specifies whether the map view is displayed as a fixed map that the user cannot change. Optional. Default is false.</param>
        ///// <param name="mode" type="VEMapMode">Specifies whether to load the map in 2D or 3D mode. Optional. Default is VEMapMode.Mode2D.</param>
        ///// <param name="showSwitch" type="Boolean">Specifies whether to show the map mode switch on the dashboard control. Optional. Default is true (the switch is displayed).</param>
        //public void LoadMap(VELatLong latLong, int zoom, VEMapStyle style, bool setFixed, VEMapMode mode, bool showSwitch)
        //{
        //    string strStyle = new string((char)style, 1); // convert to string
        //    Invoke("LoadMap", (ScriptObject)latLong, zoom, strStyle, setFixed, mode, showSwitch);
        //}

        ///// <summary>Loads the specified map. All parameters are optional.</summary>
        ///// <param name="latLong" type="VELatLong">A VELatLong Class object that represents the center of the map. Optional.</param>
        ///// <param name="zoom" type="Number">The zoom level to display. Valid values range from 1 through 19. Optional. Default is 4.</param>
        ///// <param name="style" type="VEMapStyle">A VEMapStyle Enumeration value specifying the map style. Optional. Default is VEMapStyle.Road.</param>
        ///// <param name="setFixed" type="Boolean">Specifies whether the map view is displayed as a fixed map that the user cannot change. Optional. Default is false.</param>
        ///// <param name="mode" type="VEMapMode">Specifies whether to load the map in 2D or 3D mode. Optional. Default is VEMapMode.Mode2D.</param>
        ///// <param name="showSwitch" type="Boolean">Specifies whether to show the map mode switch on the dashboard control. Optional. Default is true (the switch is displayed).</param>
        ///// <param name="tileBuffer" type="Number">How much tile buffer to use when loading map. Default is 1 (load an extra boundary of one tile). This parameter is ignored in 3D mode.</param>		
        //public void LoadMap(VELatLong latLong, int zoom, VEMapStyle style, bool setFixed, VEMapMode mode, bool showSwitch, int tileBuffer)
        //{
        //    string strStyle = new string((char)style, 1); // convert to string
        //    Invoke("LoadMap", (ScriptObject)latLong, zoom, strStyle, setFixed, mode, showSwitch, tileBuffer);
        //}

        /// <summary>Loads the traffic map.  The traffic map is only available at zoom levels from 9 through 15, inclusively.</summary>
        /// <param name="showFlow" type="Boolean">Whether to show the traffic flow.</param>
        public void LoadTraffic(bool showFlow)
        {
            Invoke("LoadTraffic", showFlow);
        }

        /// <summary>When in 2D mode, moves the map the specified amount.  The Pan method only applies to 2D mode maps. If you are working with maps in 3D mode, use the VEMap.StartContinuousPan Method and VEMap.EndContinuousPan Method.</summary>
        /// <param name="deltaX" type="Number">The amount to move the map horizontally, in pixels</param>
        /// <param name="deltaY" type="Number">The amount to move the map vertically, in pixels</param>
        public void Pan(int deltaX, int deltaY)
        {
            Invoke("Pan", deltaX, deltaY);
        }

        /// <summary>Pans the map to a specific latitude and longitude.</summary>
        /// <param name="latlong" type="VELatLong">A VELatLong Class object that represents the latitude and longitude of the point on which to center the map</param>
        public void PanToLatLong(VELatLong latLong)
        {
            Invoke("PanToLatLong", (ScriptObject)latLong);
        }

        /// <summary>Converts a pixel (a point on the map) to a VELatLong Class object (latitude/longitude pair).</summary>
        /// <param name="pixel" type="VEPixel">VEPixel Class object representing a pixel location on the map.</param>
        /// <returns type="VELatLong"></returns> 
        public VELatLong PixelToLatLong(VEPixel pixel)
        {
            ScriptObject so = Invoke<ScriptObject>("PixelToLatLong", (ScriptObject)pixel);
            var ret = new VELatLong(so);
            return ret;
        }

        /// <summary>Get the JavaScript class name</summary>
        /// <returns type="String">The class name used in JavaScript </returns>		
        public override string ClassName
        {
            get { return thisClass; }
        }

        /// <summary>Resizes the map based on the specified width and height.  If this method is called with no parameters, the map is resized to fit the entire DIV element.</summary>
        public void Resize()
        {
            Invoke("Resize");
        }

        /// <summary>Resizes the map based on the specified width and height.  If this method is called with no parameters, the map is resized to fit the entire DIV element.</summary>
        /// <param name="width" type="Number">The width, in pixels, of the map. Optional.</param>
        /// <param name="height" type="Number">The height, in pixels, of the map. Optional.</param>
        public void Resize(int width, int height)
        {
            Invoke("Resize", width, height);
        }

        /// <summary>Changes the orientation of the existing bird's eye image (VEBirdseyeScene Class object) to the specified orientation.</summary>
        /// <param name="orientation" type="VEOrientation "></param>
        public void SetBirdseyeOrientation(VEOrientation orientation)
        {
            Invoke("SetBirdseyeOrientation", ScriptEnumConverter.ToString(orientation));
        }

        /// <summary>Displays the bird's eye image specified by the VEBirdseyeScene Class ID.</summary>
        /// <param name="id" type="Number">The ID of the VEBirdseyeScene Class object that you want to display</param>
        public void SetBirdseyeScene(int id)
        {
            Invoke("SetBirdseyeScene", id);
        }

        /// <summary>Displays the bird's eye image specified by the center of the map, North direction, zoom 1</summary>
        public void SetBirdseyeScene()
        {
            Invoke("SetBirdseyeScene");
        }

        /// <summary>Displays the bird's eye image specified by the center of the map, the orientation, and the zoom level</summary>
        /// <param name="latLong" type="VELatLong">A VELatLong Class object specifying the center of the image. Optional. If this parameter is not supplied the center of the map is used.</param>
        public void SetBirdseyeScene(VELatLong latLong)
        {
            Invoke("SetBirdseyeScene", (ScriptObject)latLong);
        }

        /// <summary>Displays the bird's eye image specified by the center of the map, the orientation, and the zoom level</summary>
        /// <param name="latLong" type="VELatLong">A VELatLong Class object specifying the center of the image. Optional. If this parameter is not supplied the center of the map is used.</param>
        /// <param name="orientation" type="VEOrientation">A VEOrientation Enumeration value specifying the direction to which which the image is viewed. Optional. If this value is not supplied, the default value VEOrientation.North is used.</param>
        public void SetBirdseyeScene(VELatLong latLong, VEOrientation orientation)
        {
            Invoke("SetBirdseyeScene", (ScriptObject)latLong, ScriptEnumConverter.ToString(orientation));
        }

        /// <summary>Displays the bird's eye image specified by the center of the map, the orientation, and the zoom level</summary>
        /// <param name="latLong" type="VELatLong">A VELatLong Class object specifying the center of the image. Optional. If this parameter is not supplied the center of the map is used.</param>
        /// <param name="orientation" type="VEOrientation">A VEOrientation Enumeration value specifying the direction to which which the image is viewed. Optional. If this value is not supplied, the default value VEOrientation.North is used.</param>
        /// <param name="zoomLevel" type="Number">The level of zoom. Optional. If this parameter is not supplied, the value 1 is used.</param>
        public void SetBirdseyeScene(VELatLong latLong, VEOrientation orientation, int zoomLevel)
        {
            Invoke("SetBirdseyeScene", (ScriptObject)latLong, ScriptEnumConverter.ToString(orientation), zoomLevel);
        }

        /// <summary>Displays the bird's eye image specified by the center of the map, the orientation, and the zoom level</summary>
        /// <param name="latLong" type="VELatLong">A VELatLong Class object specifying the center of the image. Optional. If this parameter is not supplied the center of the map is used.</param>
        /// <param name="orientation" type="VEOrientation">A VEOrientation Enumeration value specifying the direction to which which the image is viewed. Optional. If this value is not supplied, the default value VEOrientation.North is used.</param>
        /// <param name="zoomLevel" type="Number">The level of zoom. Optional. If this parameter is not supplied, the value 1 is used.</param>
        /// <param name="callback">A Boolean value that indicates if the BirdseyeCompleteEvent should be fired when the SetBirdseyeScene method completes.</param>
        public void SetBirdseyeScene(VELatLong latLong, VEOrientation orientation, int zoomLevel, bool callback)
        {
            // call a proxy function in Javascript because our callbacks won't pass the (typeof = "function") test used to validate parameters
            HtmlPage.Window.Invoke("SetBirdseyeSceneJS", (ScriptObject)this, (ScriptObject)latLong, ScriptEnumConverter.ToString(orientation), zoomLevel, callback);
            //Invoke("SetBirdseyeScene", (ScriptObject)veLatLong, orientation, zoomLevel, callback);
        }

        /// <summary>
        /// Sets the client token for clients with a commercial VE contracts 
        /// </summary>
        /// <param name="token">token returned from Virtual Earth Platform Token Service call as detailed here: http://msdn.microsoft.com/en-us/library/bb924353.aspx </param>
        /// <remarks>
        /// Setting the client token allows additional functionality on the map such as having multiple routes displayed on a single map. 
        /// </remarks>
        public void SetClientToken(string token)
        {
            HtmlPage.Window.Invoke("SetVEClientToken", (ScriptObject)this, token);
        }


        /// <summary>Sets the 2D map view to include all of the points, lines, or polygons specified in the provided array</summary>
        /// <param name="arrPoint" type="Array">an array of VELatLong Class points </param>	   
        public void SetMapView(VELatLong[] points)
        {
            JSArray<ScriptObject> arrPoint = ConvertToScriptObjectJSArray(points);
            Invoke("SetMapView", (ScriptObject)arrPoint);
        }

        /// <summary>Sets the 3D map view to the view defined by a VEMapViewSpecification Class object.</summary>
        /// <param name="mapviewSpec">In 3D mode, can also be a VEMapViewSpecification Class object. This object defines the location, altitude, pitch, and heading to use for the map view.</param>	   
        public void SetMapView(VEMapViewSpecification mapViewSpec)
        {
            Invoke("SetMapView", (ScriptObject)mapViewSpec);
        }

        /// <summary>Specifies whether to zoom to the center of the screen or to the cursor position on the screen.</summary>
        /// <param name="zoomToCenter" type="Boolean">A Boolean value specifying whether to zoom to the center of the screen or to the cursor position. If true, the map control zooms to the center of the screen; if false, the map control zooms to the cursor position on the screen.</param>	   
        public void SetMouseWheelZoomToCenter(bool zoomToCenter)
        {
            Invoke("SetMouseWheelZoomToCenter", zoomToCenter);
        }

        /// <summary>Gets or sets a double that represents the pitch, where 0 is level and -90 is straight down.</summary>
        /// <value>The pitch, where 0 is level and -90 is straight down.</value>
        /// <remarks>This member is only available in 3D mode.</remarks>
        public double Pitch
        {
            get { return Invoke<double>("GetPitch"); }
            set { Invoke("SetPitch", value); }
        }

        /// <summary>Sets the distance unit (kilometers or miles) for the map scale.</summary>
        /// <param name="distanceUnit" type="VEDistanceUnit">A VEDistanceUnit Enumeration value that specifies either miles or kilometers.</param>	   
        public void SetScaleBarDistanceUnit(VEDistanceUnit distanceUnit)
        {
            string str = new string((char)distanceUnit, 1);
            Invoke("SetScaleBarDistanceUnit", str);
        }

        /// <summary>Specifies the accuracy in converting shapes when the map style is changed to birdseye.</summary>
        /// <param name="policy" type="VEShapeAccuracy">The VEShapeAccuracy Enumeration value specifying the accuracy in converting shapes.</param>	   
        public void SetShapesAccuracy(VEShapeAccuracy policy)
        {
            Invoke("SetShapesAccuracy", policy);
        }

        /// <summary>Specifies the maximum number of shapes that are accurately converted at one time when the map style is changed to birdseye.</summary>
        /// <param name="max" type="Number">The maximum number of shapes that are accurately converted.</param>	   
        public void SetShapesAccuracyRequestLimit(int max)
        {
            Invoke("SetShapesAccuracyRequestLimit", max);
        }

        /// <summary>Sets the number of "rings" of map tiles that should be loaded outside of the visible mapview area. This is also called tile overfetching.</summary>
        /// <param name="numRings" type="Number">An integer value greater than or equal to 0 that indicates the number of rings of additional tiles that should be loaded. The default is 0, and the maximum is 3.</param>	   
        public void SetTileBuffer(int rings)
        {
            Invoke("SetTileBuffer", rings);
        }

        /// <summary>Specifies the text shown with the traffic legend, if visible.</summary>
        /// <param name="text" type="String">A string specifying the text shown with the traffic legend.</param>	   
        public void SetTrafficLegendText(string text)
        {
            Invoke("SetTrafficLegendText", text);
        }

        /// <summary>Gets or sets the zoom level of the current map view.</summary>
        /// <value>The zoom level of the current map view.</value>
        /// <remarks>Valid values range from 1 through 19.</remarks>
        public int ZoomLevel
        {
            get { return Invoke<int>("GetZoomLevel"); }
            set { Invoke("SetZoomLevel", value); }
        }

        /// <summary>In 3D mode, shows the default user interface for controlling the map in 3D mode. By default, this control is shown.</summary>
        public void Show3DNavigationControl()
        {
            Invoke("Show3DNavigationControl");
        }

        /// <summary>Shows all shape layers on the map.</summary>
        public void ShowAllShapeLayers()
        {
            Invoke("ShowAllShapeLayers");
        }

        /// <summary>Makes the specified control visible. This method only affects control elements that have been hidden from view using the VEMap.HideControl Method.</summary>
        /// <param name="element">An HTML element that contains the control to be shown.</param>	   
        public void ShowControl(HtmlElement element)
        {
            Invoke("ShowControl", element);
        }

        /// <summary>Shows the default user interface for controlling the map (the compass-and-zoom control). By default, this control is shown.</summary>
        public void ShowDashboard()
        {
            Invoke("ShowDashboard");
        }

        /// <summary>Specifies whether the default disambiguation dialog is displayed when multiple results are returned from a location query using the VEMap.GetDirections Method.</summary>
        /// <param name="showDialog" type="Boolean">A Boolean value. True enables the disambiguation dialog; false disables it.</param>	   
        public void ShowDisambiguationDialog(bool showDialog)
        {
            Invoke("ShowDisambiguationDialog", showDialog);
        }

        /// <summary>Shows the Find control, which enables users to enter search queries.</summary>
        public void ShowFindControl()
        {
            Invoke("ShowFindControl");
        }

        /// <summary>Shows an information box for the shape.</summary>
        /// <param name="shape" type="VEShape">The reference to the shape for which an info box is to be shown. Required.</param>	   
        public void ShowInfoBox(VEShape shape)
        {
            Invoke("ShowInfoBox", (ScriptObject)shape);
        }

        /// <summary>Shows an information box for the shape.</summary>
        /// <param name="shape" type="VEShape">The reference to the shape for which an info box is to be shown. Required.</param>	   
        /// <param name="anchor" type="VEPixel">The anchor point where the info box is docked when displayed. This VEPixel Class object must be a valid point on the current map. Optional.</param>	   
        public void ShowInfoBox(VEShape shape, VEPixel anchor)
        {
            Invoke("ShowInfoBox", (ScriptObject)shape, (ScriptObject)anchor);
        }

        /// <summary>Shows an information box for the shape.</summary>
        /// <param name="shape" type="VEShape">The reference to the shape for which an info box is to be shown. Required.</param>	   
        /// <param name="anchor" type="VEPixel">The anchor point where the info box is docked when displayed. This VEPixel Class object must be a valid point on the current map. Optional.</param>	   
        /// <param name="offset" type="VEPixel">If the anchor point is a VELatLong object, this parameter, a VEPixel object, specifies the anchor point's offset from that latlong position. Optional.</param>	   
        public void ShowInfoBox(VEShape shape, VEPixel anchor, VEPixel offset)
        {
            Invoke("ShowInfoBox", (ScriptObject)shape, (ScriptObject)anchor, (ScriptObject)offset);
        }

        /// <summary>Shows an information box for the shape.</summary>
        /// <param name="shape" type="VEShape">The reference to the shape for which an info box is to be shown. Required.</param>	   
        /// <param name="anchor" type="VELatLong">The anchor point where the info box is docked when displayed. This VELatLong Class object must be a valid point on the current map. Optional.</param>	   
        /// <param name="offset" type="VEPixel">If the anchor point is a VELatLong object, this parameter, a VEPixel object, specifies the anchor point's offset from that latlong position. Optional.</param>	   
        public void ShowInfoBox(VEShape shape, VELatLong anchor)
        {
            Invoke("ShowInfoBox", (ScriptObject)shape, (ScriptObject)anchor);
        }

        /// <summary>Shows an information box for the shape.</summary>
        /// <param name="shape" type="VEShape">The reference to the shape for which an info box is to be shown. Required.</param>	   
        /// <param name="anchor" type="VELatLong">The anchor point where the info box is docked when displayed. This VELatLong Class object must be a valid point on the current map. Optional.</param>	   
        /// <param name="offset" type="VEPixel">If the anchor point is a VELatLong object, this parameter, a VEPixel object, specifies the anchor point's offset from that latlong position. Optional.</param>	   
        public void ShowInfoBox(VEShape shape, VELatLong anchor, VEPixel offset)
        {
            Invoke("ShowInfoBox", (ScriptObject)shape, (ScriptObject)anchor, (ScriptObject)offset);
        }

        /// <summary>Displays the specified message in a dialog box on the map.</summary>
        /// <param name="message" type="String">The message you want to display on the map.</param>	   
        public void ShowMessage(string message)
        {
            Invoke("ShowMessage", message);
        }

        /// <summary>Displays the mini map.</summary>
        public void ShowMiniMap()
        {
            Invoke("ShowMiniMap");
        }

        /// <summary>Displays the mini map at the specified offset from the top left corner of the screen.</summary>
        /// <param name="offsetX" type="Number">The x coordinate offset as a number of pixels from the top left corner of the screen. Optional.</param>	   
        /// <param name="offsetY" type="Number">The y coordinate offset as a number of pixels from the top left corner of the screen. Optional.</param>	   
        public void ShowMiniMap(int offsetX, int offsetY)
        {
            Invoke("ShowMiniMap", offsetX, offsetY);
        }

        /// <summary>Displays the mini map at the specified offset from the top left corner of the screen.</summary>
        /// <param name="offsetX" type="Number">The x coordinate offset as a number of pixels from the top left corner of the screen. Optional.</param>	   
        /// <param name="offsetY" type="Number">The y coordinate offset as a number of pixels from the top left corner of the screen. Optional.</param>	   
        /// <param name="size" type="VEMiniMapSize">A VEMiniMapSize Enumeration value that specifies the mini map size. Optional. Default value is VEMiniMapSize.Small.</param>	   
        public void ShowMiniMap(int offsetX, int offsetY, VEMiniMapSize size)
        {
            Invoke("ShowMiniMap", offsetX, offsetY, ScriptEnumConverter.ToString(size));
        }

        /// <summary>Displays the scale bar.</summary>
        public void ShowScalebar()
        {
            Invoke("ShowScalebar");
        }

        /// <summary>Shows a tile layer on the map.</summary>
        /// <param name="layerId" type="String">The ID of the layer to be shown.</param>	   
        public void ShowTileLayer(string layerId)
        {
            Invoke("ShowTileLayer", layerId);
        }

        /// <summary>Displays the traffic legend.</summary>
        /// <param name="x" type="Number">The x-coordinate of the top-left corner of the legend. Optional.</param>	   
        /// <param name="y" type="Number">The y-coordinate of the top-left corner of the legend. Optional.</param>
        public void ShowTrafficLegend(int x, int y)
        {
            Invoke("ShowTrafficLegend", x, y);
        }

        /// <summary>Displays the traffic legend at default location (bottom-right).</summary>
        public void ShowTrafficLegend()
        {
            Invoke("ShowTrafficLegend");
        }

        /// <summary>Moves the map in the specified direction until the VEMap.EndContinuousPan Method is called.</summary>
        /// <param name="x" type="Number">The speed, as a percentage of the fastest speed, to move the map in the x direction. Positive numbers move the map to the right, while negative numbers move the map to the left.</param>	   
        /// <param name="y" type="Number">The speed, as a percentage of the fastest speed, to move the map in the y direction. Positive numbers move the map down, while negative numbers move the map up</param>
        public void StartContinuousPan(int x, int y)
        {
            Invoke("StartContinuousPan", x, y);
        }

        /// <summary>Increases the map zoom level by 1.  Valid values range from 1 through 19. If you call the ZoomIn method when the current zoom level is already at the maximum, the zoom level does not change.</summary>
        public void ZoomIn()
        {
            Invoke("ZoomIn");
        }

        /// <summary>Decreases the map zoom level by 1.  Valid values range from 1 through 19. If you call the ZoomOut method when the current zoom level is already at the minimum, the zoom level does not change.</summary>
        public void ZoomOut()
        {
            Invoke("ZoomOut");
        }
        #endregion // Public Methods
        
        #region Public Properties
        /// <summary>Gets or sets a double that represents the altitude (in meters) above the geoid.</summary>
        /// <value>A double that represents the altitude (in meters) above the geoid.</value>
        /// <remarks>This member is only available in 3D mode.</remarks>
        public double Altitude
        {
            get { return Invoke<double>("GetAltitude"); }
            set { Invoke("SetAltitude", value); }
        }
        
        /// <summary>Gets the current Birdseye scene if the map is in bird's mode.</summary>
        /// <value>The current Birdseye scene if the map is in bird's mode.</value>
        public VEBirdseyeScene BirdseyeScene
        {
            get
            {
                ScriptObject so = Invoke<ScriptObject>("GetBirdseyeScene");
                var ret = new VEBirdseyeScene(so);
                return ret;
            }
        }

        /// <summary>Gets or sets the center latitude and longitude of the map.</summary>
        /// <value>A <see cref="VELatLong"/> that indicates the center of the map.</value>
        public VELatLong Center
        {
            get
            {
                ScriptObject so = Invoke<ScriptObject>("GetCenter");
                var ret = new VELatLong(so);
                return ret;
            }
            set { Invoke("SetCenter", (ScriptObject)value); }
        }

        /// <summary>Gets or sets a double that represents the compass heading, where 0 is true north and 180 is true south.</summary>
        /// <value>The compass heading, where 0 is true north and 180 is true south.</value>
        /// <remarks>This member is only available in 3D mode.</remarks>
        public double Heading
        {
            get { return Invoke<double>("GetHeading"); }
            set { Invoke("SetHeading", value); }
        }

        /// <summary>Gets the pixel value of the left edge of the map control.</summary>
        /// <value>The pixel value of the left edge of the map control.</value>
        public int Left
        {
            get
            {
                return Invoke<int>("GetLeft");
            }
        }

        /// <summary>Gets or sets the current map mode.</summary>
        /// <value>A <see cref="VEMapMode"/> value that indicates the current map mode.</value>
        public VEMapMode MapMode
        {
            get { return (VEMapMode)Invoke<int>("GetMapMode"); }
            set { Invoke("SetMapMode", value); }
        }

        /// <summary>Gets or sets the current map style.</summary>
        /// <value>A <see cref="VEMapStyle"/> indicating the current map style.</value>
        public VEMapStyle MapStyle
        {
            get
            {
                string str = Invoke<string>("GetMapStyle");
                return (VEMapStyle)str[0];
            }
            set
            {
                string str = new string((char)value, 1); // convert to string
                Invoke("SetMapStyle", str);
            }
        }

        /// <summary>Gets or sets the 2D map view as a <see cref="VELatLongRectangle"/>.</summary>
        /// <value>The 2D map view as a <see cref="VELatLongRectangle"/>.</value>
        public VELatLongRectangle MapView
        {
            get
            {
                // in birdseye mode you have to get the rectangle from the BirdseyeScene structure
                if (MapStyle == VEMapStyle.Birdseye)
                {
                    VEBirdseyeScene scene = BirdseyeScene;
                    var retB = scene.BoundingRectangle;
                    return retB;
                }
                ScriptObject so = Invoke<ScriptObject>("GetMapView");
                var ret = new VELatLongRectangle(so);
                return ret;
            }
            set
            {
                Invoke("SetMapView", (ScriptObject)value);
            }
        }

        /// <summary>Gets the total number of shape layers on the map.</summary>
        /// <value>the total number of shape layers on the map.</value>
        public int ShapeLayerCount
        {
            get
            {
                double dbl = Invoke<double>("GetShapeLayerCount");
                return (int)dbl;
            }
        }

        /// <summary>Gets the number of tile layers.</summary>
        /// <value>The number of tile layers.</value>
        public int TileLayerCount
        {
            get { return Invoke<int>("GetTileLayerCount"); }
        }

        /// <summary>The pixel value of the Top edge of the map control.</summary>
        public int Top
        {
            get { return Invoke<int>("GetTop"); }
        }

        /// <summary>Gets the current version of the map control.</summary>
        /// <value>The current version of the map control.</value>
        public string Version
        {
            get
            {
                return (string)ScriptObject.InvokeSelf("GetVersion");
            }
        }
        #endregion // Public Properties
        
        #region Public Events
        #region Mouse Events
        /// <summary>
        /// Occurs when a left or right mouse button is single-clicked.
        /// </summary>
        public event EventHandler<VEMapEventArgs> Click;

        /// <summary>
        /// Occurs when a left mouse button is double-clicked.
        /// </summary>
        public event EventHandler<VEMapEventArgs> DoubleClick;

        /// <summary>
        /// Occurs when a mouse button (left, right, or middle) is clicked (but before it is released).
        /// </summary>
        public event EventHandler<VEMapEventArgs> MouseDown;

        /// <summary>
        /// Occurs when the mouse cursor moves. This is not supported in 3D mode.
        /// </summary>
        public event EventHandler<VEMapEventArgs> MouseMove;
        
        /// <summary>
        /// Occurs when the mouse cursor moves away from a <see cref="VEShape"/>.
        /// </summary>
        public event EventHandler<VEMapEventArgs> MouseOut;

        /// <summary>
        /// Occurs when the mouse cursor moves over a <see cref="VEShape"/>.
        /// </summary>
        public event EventHandler<VEMapEventArgs> MouseOver;

        /// <summary>
        /// Occurs when a mouse button (left, right, or middle) is released.
        /// </summary>
        public event EventHandler<VEMapEventArgs> MouseUp;

        /// <summary>
        /// Occurs when the mouse wheel is moved. This method is not supported in 3D mode, and the 
        /// coordinate values returned in Firefox 1.5 and 2.0 are not correct.
        /// </summary>
        public event EventHandler<VEMapEventArgs> MouseWheel;
        #endregion // Mouse Events

        #region Keyboard Events
        /// <summary>
        /// Occurs when a key is pressed (but before it is released). This is not supported in 3D mode.
        /// </summary>
        public event EventHandler<VEMapEventArgs> KeyDown;

        /// <summary>
        /// Occurs when a key is pressed and released. This is not supported in 3D mode.
        /// </summary>
        public event EventHandler<VEMapEventArgs> KeyPress;

        /// <summary>
        /// Occurs when a key is released. This is not supported in 3D mode.
        /// </summary>
        public event EventHandler<VEMapEventArgs> KeyUp;
        #endregion // Keyboard Events

        #region General Events
        /// <summary>
        /// Occurs only when the bird's eye image scene ID is changed. This event fires only if the map is currently displaying a bird's eye image and that image is changed.
        /// </summary>
        public event EventHandler<VEMapEventArgs> BirdseyeChanged;

        /// <summary>
        /// Occurs when a Birdseye operation has completed.
        /// </summary>
        public event EventHandler<BirdseyeCompletedEventArgs> BirdseyeCompleted;

        /// <summary>
        /// Occurs when bird's eye images are available at the center of the current map.
        /// </summary>
        public event EventHandler<VEMapEventArgs> BirdseyeEntered;

        /// <summary>
        /// Occurs when bird's eye images are no longer available at the center of the current map.
        /// </summary>
        public event EventHandler<VEMapEventArgs> BirdseyeLeft;
        
        /// <summary>
        /// Occurs when there is a map control error.
        /// </summary>
        public event EventHandler<VEMapEventArgs> Error;

        /// <summary>
        /// Occurs when a Find operation has completd.
        /// </summary>
        public event EventHandler<FindCompletedEventArgs> FindCompleted;

        /// <summary>
        /// Occurs when a 3D Model import operation has completed.
        /// </summary>
        public event EventHandler<Import3DModelCompletedEventArgs> Import3DModelCompleted;

        /// <summary>
        /// Occurs when an import operation has completed.
        /// </summary>
        public event EventHandler<ImportShapeLayerDataCompletedEventArgs> ImportShapeLayerDataCompleted;

        /// <summary>
        /// Occurs when the map is first loaded.
        /// </summary>
        public event EventHandler MapLoaded;

        /// <summary>
        /// Occurs when the map style changes.
        /// </summary>
        public event EventHandler<VEMapEventArgs> MapStyleChanged;

        /// <summary>
        /// Occurs after the map mode changes and the map has reloaded.
        /// </summary>
        public event EventHandler<VEMapEventArgs> ModeInitialized;

        /// <summary>
        /// Occurs when the map mode fails to change to 3D mode.
        /// </summary>
        public event EventHandler<VEMapEventArgs> ModeNotAvailable;

        /// <summary>
        /// Occurs when a pan of the map begins. This event is not supported in 3D mode.
        /// </summary>
        public event EventHandler<VEMapEventArgs> PanEnded;

        /// <summary>
        /// Occurs when a pan of the map ends.
        /// </summary>
        public event EventHandler<VEMapEventArgs> PanStarted;

        /// <summary>
        /// Occurs when the map is resized.
        /// </summary>
        public event EventHandler<VEMapEventArgs> Resized;

        /// <summary>
        /// Occurs when a route operation has completed.
        /// </summary>
        public event EventHandler<RouteCompletedEventArgs> RouteCompleted;

        /// <summary>
        /// Occurs whenever the map view changes.
        /// </summary>
        public event EventHandler<VEMapEventArgs> ViewChanged;

        /// <summary>
        /// Occurs when the map zoom ends.
        /// </summary>
        public event EventHandler<VEMapEventArgs> ZoomEnded;

        /// <summary>
        /// Occurs when the map zoom begins.
        /// </summary>
        public event EventHandler<VEMapEventArgs> ZoomStarted;
        #endregion // General Events
        #endregion // Public Events
    }
}
